package com.coco.component;

import com.coco.config.MyEndpointConfigure;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

@ServerEndpoint(value = "/ws/asset",configurator= MyEndpointConfigure.class)
@Component
public class WebSocketServer {

    private static Logger log = LoggerFactory.getLogger(WebSocketServer.class);
    private static final AtomicInteger OnlineCount = new AtomicInteger(0);
    // concurrent包的线程安全Set，用来存放每个客户端对应的Session对象。
    private static CopyOnWriteArraySet<Session> SessionSet = new CopyOnWriteArraySet<Session>();

    private static Map<Session,String> userSession = new ConcurrentHashMap<>(16);

    @Resource
    private MyDiscoveryClient myDiscoveryClient;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session) {
        SessionSet.add(session);
        userSession.put(session, UUID.randomUUID().toString());
        int cnt = OnlineCount.incrementAndGet();
        log.info("有新的连接加入，当前连接数为：{}",cnt);
        SendMessage(session, "连接成功");
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onCLose(Session session) {
        if(SessionSet.contains(session)) {
            SessionSet.remove(session);
            int cnt = OnlineCount.decrementAndGet();
            log.info("有连接关闭，当前连接数为：{}", cnt);
        }
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message,Session session) {
        log.info("来自客户端的消息：{}",message);
        String id = session.getId();
        //群发消息
        BroadCastInfo(id + "："+message);
        try{
            log.info("session: {}" ,session);
            String uuid = userSession.get(session);
            String msg = uuid + "=" + message;
            myDiscoveryClient.sendMsgToService(msg);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 出现错误
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session,Throwable error) {
        log.error("发生错误：{}，Session ID： {}",error.getMessage(),session.getId());
        error.printStackTrace();
    }

    /**
     * 发送消息，实践表明，每次浏览器刷新，session会发生变化。
     * @param session
     * @param message
     */
    public void SendMessage(Session session, String message) {
        try{
            session.getBasicRemote().sendText(message);
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 群发消息
     */
    public void BroadCastInfo(String message){
        if(message.contains("=")) {
            String[] s = message.split("=");
            String uuid = s[0];
            String msg = s[1];
            if(!userSession.containsValue(uuid)) {
                for (Session session : SessionSet) {
                    if(session.isOpen()){
                        SendMessage(session, msg);
                    }
                }
            }
        }else {
            for (Session session : SessionSet) {
                if(session.isOpen()){
                    SendMessage(session, message);
                }
            }
        }
    }

    /**
     * 指定Session发送消息
     * @param sessionId
     * @param message
     * @throws IOException
     */
    public void SendMessage(String message,String sessionId) throws IOException {
        Session session = null;
        for (Session s : SessionSet) {
            if(s.getId().equals(sessionId)){
                session = s;
                break;
            }
        }
        if(session!=null){
            SendMessage(session, message);
        }
        else{
            log.warn("没有找到你指定ID的会话：{}",sessionId);
        }
    }

    /**
     * 校验该Session是否在本台服务器上
     */
    public Boolean isExistSession(String value) {
        return userSession.containsValue(value);
    }

}
